package com.echo.code.thread.mode.observer;

import java.util.Objects;

/**
 * ConcreteObserver Created by baiyap on 2018/9/24.
 */
public class ConcreteObserver<T> implements Observable {

    private final LifeHandler handler;

    private final Runnable task;

    private LifeStatus status;

    public ConcreteObserver(LifeHandler handler, Runnable task) {
        Objects.requireNonNull(handler, "handler is required");
        Objects.requireNonNull(task, "task is required");
        this.handler = handler;
        this.task = task;
    }

    @Override
    public void start() {
        new Thread(() -> {
            try {
                this.update(LifeStatus.STARTED, null, null);
                task.run();
                this.update(LifeStatus.DONE, null, null);
            } catch (Throwable t) {
                this.update(LifeStatus.ERROR, null, t);
            }
        }).start();
    }

    @Override
    public LifeStatus getStatus() {
        return status;
    }

    private void update(LifeStatus status, T result, Throwable throwable) {
        this.status = status;
        switch (status) {
            case STARTED:
                handler.onStart(Thread.currentThread());
                break;
            case DONE:
                handler.onDone(Thread.currentThread());
                break;
            default:
                handler.onError(Thread.currentThread(), throwable);
        }
    }
}

